

#include "formation.h"
#include "gamedatamanager.h"

/*
	 serialization format
	formation block
	{
	1 byte          format version
	2 bytes         size
	50 bytes        name
	5 bytes         orders
	90 bytes        grid values
	1 byte          unit count
	n unit block
	} 149 + 62 * n

	unit block
	{
	50 bytes        name
	2 bytes         id
	2 bytes         creature
	2 bytes         weapon
	2 bytes         armor
	2 bytes         shield
	2 bytes         special
	} total 62 bytes

	*/
const char* FormationInfo::toBytes() const {
	size_t count = getChunkByteCount();
	char* buf = new char[count];
	memset(buf, 0, count);

	char* p = buf;
	*p++ = (char)1;
	*p++ = (char)(count >> 8);
	*p++ = (char)(count & 0xff);

	memcpy(p, name.c_str(), name.size());

	p += 50;

	for(int i = 0; i < SQUAD_COUNT; i++) {
		*p++ = (char)orders[i];
	}

	for(int i = 0; i < TOTAL_LINES; i++) {
		for(int j = 0; j < ROWS_PER_LINE; j++) {
			*p++ = (char)getUnitID(grids[i][j]);
		}
	}

	*p = (char)units.size();
	p++;

	for(auto it = units.begin(); it != units.end(); it++) {
		const UnitInfo& info = *it;
		memcpy(p, info.name.c_str(), info.name.size());
		p += 50;

		*p++ = (char)(info.id >> 8);
		*p++ = (char)(info.id & 0xff);

		int equipmentID = GDM->equipmentsAttribute[info.creature].id;
		*p++ = (char)(equipmentID >> 8);
		*p++ = (char)(equipmentID & 0xff);

		equipmentID = GDM->equipmentsAttribute[info.weapon].id;
		*p++ = (char)(equipmentID >> 8);
		*p++ = (char)(equipmentID & 0xff);

		equipmentID = GDM->equipmentsAttribute[info.armor].id;
		*p++ = (char)(equipmentID >> 8);
		*p++ = (char)(equipmentID & 0xff);

		equipmentID = GDM->equipmentsAttribute[info.shield].id;
		*p++ = (char)(equipmentID >> 8);
		*p++ = (char)(equipmentID & 0xff);

		equipmentID = GDM->equipmentsAttribute[info.special].id;
		*p++ = (char)(equipmentID >> 8);
		*p++ = (char)(equipmentID & 0xff);
	}

	return buf;
}

FormationInfo FormationInfo::fromBytes(char const *buf) {
	FormationInfo f;

	const char* p = buf;
	p += 3;

	f.name = p;

	p += 50;

	for(int i = 0; i < SQUAD_COUNT; i++) {
		f.orders[i] = (SquadOrder)(*p++);
	}

	p = buf;
	p += 148;
	int unitCount = *p;
	p++;
	for(int i = 0; i < unitCount; i++) {
		UnitInfo info;
		info.name = p;

		p += 50;
		info.id = ((*p) << 8) + (*(p + 1));
		p += 2;

		int equipmentID = ((*p) << 8) + (*(p + 1));
		if(equipmentID < 0) {
			equipmentID += 65536;
		}
		info.creature = GDM->equipmentIDMapping[equipmentID];
		p += 2;
		equipmentID = ((*p) << 8) + (*(p + 1));
		if(equipmentID < 0) {
			equipmentID += 65536;
		}
		info.weapon = GDM->equipmentIDMapping[equipmentID];
		p += 2;
		equipmentID = ((*p) << 8) + (*(p + 1));
		if(equipmentID < 0) {
			equipmentID += 65536;
		}
		info.armor = GDM->equipmentIDMapping[equipmentID];
		p += 2;
		equipmentID = ((*p) << 8) + (*(p + 1));
		if(equipmentID < 0) {
			equipmentID += 65536;
		}
		info.shield = GDM->equipmentIDMapping[equipmentID];
		p += 2;
		equipmentID = ((*p) << 8) + (*(p + 1));
		if(equipmentID < 0) {
			equipmentID += 65536;
		}
		info.special = GDM->equipmentIDMapping[equipmentID];
		p += 2;

		f.units.push_back(info);
	}

	p = buf;
	p += 58;
	for(int i = 0; i < TOTAL_LINES; i++) {
		for(int j = 0; j < ROWS_PER_LINE; j++) {
			int id = *p++;
			if(id > 0) {
				f.grids[i][j] = f.getUnitName(id);
			}
		}
	}

	return f;
}

